package com.dobbinsoft.iotechn.apigw.controller;

import com.dobbinsoft.iotechn.core.exception.ServiceException;
import com.dobbinsoft.iotechn.data.logger.Logger;
import com.dobbinsoft.iotechn.data.logger.LoggerFactory;
import com.dobbinsoft.iotechn.device.api.biz.DeviceBizService;
import com.dobbinsoft.iotechn.device.constant.DeviceConst;
import com.dobbinsoft.iotechn.device.enums.IotMessageType;
import com.dobbinsoft.iotechn.device.mqtt.IotMqttClient;
import com.dobbinsoft.iotechn.device.mqtt.message.IotDeviceDisconnectMessage;
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.*;

/**
 * Description: EMQ权限鉴定控制器
 * User: rize
 * Date: 2020/6/21
 * Time: 16:52
 */
@RestController
@RequestMapping("/emqx")
public class EmqxController implements InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(EmqxController.class);

    @Autowired
    private DeviceBizService deviceBizService;

    @Autowired
    private IotMqttClient iotMqttClient;

    @Value("${com.dobbinsoft.iotechn.mqtt.server-ip}")
    private String whiteIpsStr;

    private Set<String> whiteIps;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.whiteIps = new TreeSet<>(Arrays.asList(whiteIpsStr.split(",")));
    }

    @RequestMapping("/auth")
    public ResponseEntity<?> doAuth(String clientid, String ip, String username, String password) {
        if (this.whiteIps.contains(ip)) {
            return ResponseEntity.ok("ignore");
        }
        if (!clientid.equals(username)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Forbidden!");
        }
        try {
            deviceBizService.auth(ip, username, password);
            logger.info("[设备连接] accessKeyId=" + username);
            return ResponseEntity.ok("ignore");
        } catch (ServiceException e) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Forbidden!");
        }
    }

    /**
     *
     * @param clientid
     * @param username
     * @param ip
     * @param topic
     * @param access 1: SUB 2:PUB
     * @return
     * @throws IOException
     */
    @RequestMapping("/acl")
    public ResponseEntity<?> doAcl(String clientid, String username, String ip, String topic, Integer access) throws IOException {
        if (this.whiteIps.contains(ip)) {
            return ResponseEntity.ok("ignore");
        }
        if (topic.equals(DeviceConst.TOPIC_UP + username)) {
            return ResponseEntity.ok("ignore");
        }
        if (topic.equals(DeviceConst.TOPIC_DOWN + username) && access == 1) {
            // 命令TOPIC只允许白名单IP（即内网写）
            return ResponseEntity.ok("ignore");
        }
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Forbidden!");
    }

    @RequestMapping("/sauth")
    public ResponseEntity<?> doSAuth(String ip) {
        if (this.whiteIps.contains(ip)) {
            return ResponseEntity.ok("ignore");
        }
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Forbidden!");
    }

    @RequestMapping("/hook")
    public ResponseEntity<?> onDisconnect(@RequestBody WebHookEvent event) {
        if (event.getAction() != null && event.getAction().equals("client_disconnected")) {
            IotDeviceDisconnectMessage message = new IotDeviceDisconnectMessage();
            message.setCode(IotMessageType.DISCONNECT.getCode());
            iotMqttClient.send(DeviceConst.TOPIC_UP, event.getUsername(), message);
            logger.info("[设备断开连接] clientId=" + event.getClientid());
        }
        return ResponseEntity.ok("ignore");
    }

    @Data
    public static class WebHookEvent {
        private String clientid;
        private String action;
        private String username;
    }

}


